Talk:Development plans/archive 1
Thoughts Here are some thoughts on current development issues, and things we need to consider. Mandatory rendering features: * Target profiles (DVD/SVCD/VCD, NTSC/PAL) with consideration for: ** aspect ratio at varying resolutions (i.e. text rendered to NTSC DVD 720x480 should not look radically different from text rendered to NTSC Half-DVD 352x480, at the same aspect ratio) ** frame rate (i.e. NTSC 29.97fps should not appear "faster" than PAL 25.00fps) * Image background or overlays, with customizable scaling and positioning ** ...and, by extension, video overlays consisting of a sequence of frame images * Text overlays, with customizable font, size, and color * Shape overlays (lines, rectangles, circles or polygons) with customizable metrics and color Desirable rendering features: * Alternative backends (chosen at run-time, to cut down on install-time dependencies) * Full animation capability, with keyframing of graphical attributes including: ** Transformation (position/scaling/rotation) ** Opacity/Color (RGBA channels) Subtitle considerations: * Converting from existing subtitle streams (for embedding text subtitles into an MPEG file) * Generating from scratch (for creating menu navigation elements or user-defined text subtitles for slideshows) ** May require coordinate-based "button" specification Comments? -- Wapcaplet 01:55, 27 August 2006 (UTC) Module organization One of the goals of this project is to make source code accessible--in all senses of the word--to users. (Please see , especially if you're not a developer!) Currently, these modules are in a state of some disarray. Several of them have code that is unused, or needs merging, moving, or restructuring. Some modules are looking good. Those are (in my opinion--feel free to disagree): ; : This class is pretty stable and useable. For instance, it is able to produce a nice `.m2v` file, but still not able to stick audio to it. We should restructure the encoding parts and transcoding chunks of code to somewhere more appropriate (`encoders/*.py` ?). Maybe we should create another directory structure where everything would be in a descriptive module, which does a simple job, but does it for every module. ; : Thoroughly documented (perhaps obsessively so), provides well-defined functionality; has lots of self-testing examples on how to use the module ; : Also well-documented, with a fairly straightforward interface. The is_valid() function needs to be fixed and hooked up, but otherwise I think it's a good (simpler) alternative to using getopt, making it easier to keep tovid's existing command-line style. ; : Higher-level than the other two, this one builds upon a drawing library to enable graphical rendering and display. A little weak on documentation, but has pretty good example code. The drawing backend may be changing to Cairo soon, so watch out for changes here. Some modules are needing attention: ; : This file contains MediaFile which is there to give informations about a video file. However, it has ripping and *encoding* facilities, which perhaps should be moved to a more appropriate location. `encoders/*.py` ? -- the MediaFile class should be there only to *query* information. Maybe the Video() object in `video.py` could absorb a MediaFile and convert it to something useful for transcoding, or something alike ? ; : This module calls the encoders, and does no processing itself. It contains a Video() object which should do the job, given any type of input format, to create a ready-to-burn MPEG-PS. -- This module should accept an .avi file, an .ogm, eventually a jpeg or png sequence of files, or anything containing video. Would it be okay to feed it only an audio file ? Do we have anything to deal with audio files ? -- Maybe we would need separation between audio and video processing, or call this module a `Title` or something more generic (that would include audio and video). It'd be fun to have a class that deals with *any* input, and transforms it to a compliant VOB file. Be it: * an audio file alone -> it would transcode to the right format, and add a still picture as the video (a nice speaker with the word 'Audio' as background, or a little 'Audio' icon in the middle of a black screen ?). * a video file alone -> it would create a silence file and add it to the video file. The video file would be transcoded as necessary, or multiplexed with the silence audio file if already compliant. * both an audio and video files -> transcode both, and create a compliant MPEG stream, based on `tvsys` and `format`. ; : Here we have common functions to encoders, which do not depend on `mpeg2enc` for example. The encoders are actually video encoders, and perhaps should not borrow the generic name of `encoders`. Shall we have some `vencoders` and `aencoders`, or transcoding facilities. This needs major rework. Too many hacks, tweaks, quirks here :) Maybe some other projects' structure could shed light on this problematic ? ; : Random string-formatting and other utility functions. These need categorizing or reorganization. ; : Several divergent approaches to describing and retrieving information about standard video formats like VCD, SVCD, and DVD. Needed: a single, simple interface for querying standard specifications, which allows easy addition of new formats. Should also permit easy profile-matching, to determine whether given audio/video streams are compliant with a format/tvsys. -- standards.py does that job pretty well now. We should make sure every part of libtovid calls the standards function calls to know about what parameters to use. `tvsys` and `format` are two basic things we should always know, whenever we write an application. With those parameters, we can set up frame sizes, framerates, sample rates, file formats, etc... We should make it easy to pass these parameters around in the library. (and I don't even know where to begin with fixing the GUI. It's Python written under the influence of C++, which makes it quite tangly...) Comments? -- Wapcaplet 00:40, 18 September 2006 (UTC) New file structure suggestion for libtovid Here is what I suggest as a new file structure (and code structure) for libtovid: /tovid/libtovid/gui => goes to /tovid/gui It has nothing to do with the library, does it ? : Mostly true, yeah; but this implies that it'll be installed system-wide simply as 'gui' (as in, "import gui"--not a very descriptive name). I think all tovid Python stuff needs to stay inside the libtovid folder for this reason. That way, you always know when you're importing tovid stuff. -- Wapcaplet ::Okay, good idea. So we keep `gui` inside `libtovid/` -- Wackysalut We'd have 5 directories under `libtovid`: * `render` - which would contain all drawing and animation related files * `transcode` - which would contain all the video/audio manipulation subroutines and modules. * `layout` - which would contain all the Title/Menu/Disc-related objects. Things that would make the structure of a DVD, or the contents of a menu or a title. * `templates` - which would contain implementation of renderings for different layouts, for example, a simple menu with some text as a main title. * `tests` - which would contain all the PyUnit tests : Good breakdown, overall. (Comments below). -- Wapcaplet Finally (read below), would we choose to have only a file for the transcode module, and the same for the layout module ? Keeping directories for templates, tests and render ? -- Wackysalut Sub directories contents libtovid/render Here we would put `cairo_.py` as `drawing.py`. There should be: * `animation.py` * `flipbook.py` * `effect.py` * `layer.py` * `cairo_.py` => `drawing.py` : Thanks to Python's namespace resolution, there's no reason it can't just be called 'cairo.py'. "from libtovid.render import cairo" is unambiguous. That said, though, I'd lean more towards simply 'drawing.py', since it fits with the other one-word module names better. -- Wapcaplet ::True :) --Wackysalut 14:48, 27 October 2006 (UTC) libtovid/transcode I think we should merge all the encoders into one transcoding file (transcode.py ?) and in there, different methods could be used as specified with -method on the command line (or some object properties inside the lib), to use a specific method rather than another (mpeg2enc for example), but only when necessary or when a video encoder is required. Since only the video part is encoded with a "choosable" encoder, having encoding modules separated doesn't reflect the actual behavior. Audio isn't included here, and the -method mpeg2enc means nothing for audio. Another option would be to make modules for `vencoder` (video encoder) and `aencoder` (audio encoders).. but this would make the whole thing more complicated. In fact, it's only one command that is called differently (yes, with a whole bunch of configurable parameters, I concede). There should be: * `encoders/ffmpeg.py`, `encoders/mpeg2enc.py`, `encoders/mencoder.py` => merged into one file called `video.py` ? * `audio.py` for audio manipulations ? * `__init__.py` for things used everywhere ? This needs more elaboration. Also, the current `libtovid/video.py` should not contain any encoding commands any more. It should all rely on the work of the `transcode` subdirectory modules. Same for `media.py` ? : I'm not sure about this yet... I'd prefer 'video.py' and 'audio.py' (instead of video_tr/audio_tr) if they're to be within 'transcode' anyway. I guess it partly depends on what the modules will mainly provide: classes? functions? In naming modules, I always try to consider what using it will be like. "from libtovid.transcode.video import ..." is pretty self-documenting. The 'common' stuff could even be moved to libtovid/transcode/__init__.py, if it's fundamental to transcoding, and doesn't fall in the audio/video category. -- Wapcaplet Yeah, good reflexion. I just didn't know well the namespacing stuff, I though it would conflict with other `video` modules somewhere else on the system. Would it be good to have only one file, transcode.py with all the video and audio stuff ? That would export the class Transcode().. since multiplexing has to deal with both audio and video, and wouldn't fall in either video.py or audio.py. And __init__.py wouldn't be appropriate, since it's not initialisation, but real work ? --Wackysalut 14:52, 27 October 2006 (UTC) libtovid/layout There should be in here: * `disc.py` * `menu.py` * `video.py` to be renamed to `title.py`, since video is too confusing with a video stream, but the current Video() object can also contain audio. The final destination is a Title anyway, with audio and video. This also matches more closely the dvdauthor paradigm. * `subtitles.py` - I don't know the current use of this module, so I couldn't tell if it's the exact right place, or if it could be included in some of the `menu.py` and `video.py` files. : Agreed; in fact, if we remove the command-line options stuff from disc/menu/video, and do all the XML-generation stuff from dvdauthor.py or similar, these three could even be condensed into a single file 'layout.py', containing all the data structures and logic for laying out a disc and calling the various backends to transcode and author it. Incidentally, 'subtitles.py' probably belongs in libtovid/transcode (but I'm not sure--I didn't write it, and haven't studied it closely). -- Wapcaplet Then would we have only libtovid/layout.py (following libtovid/transcode.py ?!), exporting three classes: Disc, Title, Menu ? I think that could work well. Also, the `subtitles.py` files seems to run spumux, so it might be a good place to put it in the libtovid/transcode/ section. But what if we only have one file for that ? We merge `subtitles.py` into `transcode.py` ? --Wackysalut 15:03, 27 October 2006 (UTC) libtovid/templates I think the main role of this dir is to contain different templates for menu creation. Having different rendering styles, etc.. like a thumbnails grid menu, or a list of strings with a little pointer to choose from. A multi-paged menu creating several menus in fact, all linked with python-dvdauthor ! wow :) We'd find here, for now: * `textmenu.py`, which creates a menu using several other parts. : Nice thinking! Not sure what else would be here yet, but I'm sure such a module/directory will be handy when we get around to re-implementing 'todisc' in Python... -- Wapcaplet libtovid/tests This would contain everything currently in `libtovid/tests` libtovid Here we would find: * `media.py`, which would concentrate on analysis. Maybe renamed to `analysis.py` ? * `standards.py`, which would be used by several components (encoders, layout items, templates, drawing objects, etc..) * `opts.py`, to deal with command line options in a "tovid manner". * `tdl.py`, for some apps to save a schema parseable by pytovid for example. To be determined. * `cli.py`, for all command creation functions. This to deal with command-line interfaces too. * `config.py`, if needed ?! * `stats.py`. Don't know the use currently. * `utils.py` for all sorts of string manip. routines and helper functions. : Sounds good; I'm not sure about 'media.py'. It's sort of a mish-mash right now, with some stuff that needs to be moved to a rendering/transcoding backend, and other stuff (like VideoStream & AudioStream) that just don't have a better home yet. I don't think 'analysis' is an accurate name. 'stats.py' is currently used by 'tovid-stats' for reading ~/.tovid/stats.tovid and displaying summary/averaging info; it may later be used for writing stats also. 'config.py' may become an .ini-style configuration file reader, or may just be scrapped. The rest, well... needless to say, it needs some work. -- Wapcaplet The role of `media.py` as a MediaFile() class, could be to prepare any type of material from input for running through the rest of the chain (passing through Transcode()). It could hold information about the formats the mediafile.filename contains, information on the number of channels, the language included in the file, the length, the array of images if we have a png/jpeg sequence, and the framerate, to generate a video stream. Everywhere where we would need an input file, we would assume a MediaFile, and the rest of the machine would deal with it's parameters to achieve the goal it's asked. In fact, it's already what it does, doesn't it ? -- Wackysalut For the `config.py` file, maybe it's contents coule be moved to the `pytovid` program instead of having configuration for the library itself. Since the lib could be used in a bunch of different manners and called by different programs, having a configuration file for a library itself would be odd. -- I'd leave `stats.py` since I don't know what it's used for. Maybe it doesn't have to do with the transcoding/drawing functions of the library, but it can still be there as a supporting module for the actual `tovid` suite. -- Wackysalut 15:12, 27 October 2006 (UTC) Summary To summarize, there shall be four major submodules in libtovid: ; render : A graphic & video rendering interface, suitable for creating menus & slideshows ; transcode : A video & audio encoding backend, suitable for converting files to (S)VCD or DVD target formats ; layout : A video disc authoring module, to put it all together and create a disc ; gui : All GUI-related classes and functions There will also be two additional subdirectories: ; templates : Extensible templates or styles, to aid in developing various menu, slideshow, or disc layouts ; tests : Unit tests for modules and to test higher-level use cases Other supporting modules, needed by multiple sub-components, will go in the libtovid root area. This will include things like logging facilities, command-line parsing, subprocess execution, common data structures and media formats, etc. I'd like to strive for a working, fully-tested library by version 0.30. I want to be able to author a DVD using less than 10 lines of Python code. Sound doable? -- Wapcaplet 09:06, 6 November 2006 (UTC) Top-down I've hastily outlined a top-level libtovid interface for version 0.30. For a while, I've been thinking mostly bottom-up: what building blocks are needed for doing all the stuff tovid (as a suite) needs to do? But Python is good for top-down development too, and I'd like to try to work downwards another layer: $ python >>> from libtovid import DVD Here, I'm assuming that DVD is some kind of encapsulation of what a DVD video disc is, with an interface that makes creating one easy. Most likely, DVD is a class; classes have constructors: >>> mydvd = DVD("Movie trailers", 'ntsc') From this we can infer that mydvd is now a representation of a DVD disc called "Movie trailers", and that it's NTSC format. Other than that, it's a blank disc. It needs some videos: >>> mydvd.add_videos('/pub/video/trailers') Added 12 videos to DVD disc "Movie trailers". OK, this allows you to add a directory full of videos, and prints a helpful confirmation message. The DVD object (mydvd) presumably searches that directory and stores a list of filenames. It's also safe to assume that there are other ways of adding videos (by individual filename, by reading a text file with a list of filenames, etc.) but this one just happens to be the most convenient. We can also assume that there are equally simple approaches to specifying the title of each video. DVDs gotta allow some kind of control over video quality, right? Something simple like: >>> mydvd.quality('medium') Using medium quality video encoding. Of course, this implies that you could configure other attributes about the disc--whether to use widescreen, subtitles, or multiple audio tracks, or what the maximum video bitrate should be. And of course, controlling those things on a per-video basis is a must, too. But that stuff is for advanced users, right? With 12 videos on the disc, it'll be a hassle to press "next" for each one, so it might be good to have a menu to choose them from. Like so: >>> mydvd.thumb_menu(background="/pub/images/sky.png") Creating a thumbnail menu with a background image. Hey presto, the DVD will now have a main menu showing thumbnail animations of each video, and will have "sky.png" in the background. We could most likely display some kind of a preview at this point, but we're confident in libtovid's abilities and sail on into transcoding: >>> mydvd.transcode(author=True) Encoding videos: 25%..50%..75%..100% Done! Generating menus: 25%..50%..75%..100% Done! Authoring disc: 25%..50%..75%..100% Done! DVD "Movie trailers" is done authoring. This stuff takes a long time, which is why regular updates are shown on handy progress-meters, as all the videos are encoded to compliant MPEG formats, our nice thumbnail menu is created, and the dvdauthor XML is written to author the disc. In fact, we planned on leaving this to work for several hours, so might as well author the disc too, while we're gone. Once it finishes, you can preview the DVD in a program of your choice (gxine default, say): >>> mydvd.preview() Showing preview of disc in gxine... (press ESC to exit) Looks good, so it's time to burn it: >>> mydvd.burn(speed=2) Burning DVD "Movie trailers" to /dev/dvdrw... At the very least, this should provide us with some direction towards what needs work. -- Wapcaplet 05:29, 8 November 2006 (UTC) : I've implemented some "fake" classes and functions that implement the above behavior. Install from SVN to try it out, and read the comments in (under "Target interface for version 0.30") for the rationale. -- Wapcaplet 23:45, 8 November 2006 (UTC) Easier said than done Here's how I've been approaching the implementation of this desired interface: Axioms * Say it, don't do it, unless doing it is actually easier than saying it. * If it takes several sentences to fully say it, invent a function for each sentence, and call those functions. * If there are lots of functions, put related ones into classes, and use the class's interface. * If there are lots of classes, put related ones into modules, and import those modules. Example Here's an initial implementation of the DVD class that is used in the Python examples above: class DVD: def add_videos(self, directory): print "Adding videos in %s" % directory def thumb_menu(self, background): print "Creating a thumbnail menu with a background image." All I'm doing is defining the functions I want to be able to use, and printing out what they do. These take arguments, which can be used in the print message to help say what the function is doing. self makes it object-oriented, so I can have several DVD'''s going at once. Creating a thumbnail menu is a pretty complex task, so let's assume it's all handled by a '''Menu class (which we'll define later). Pretend it has functions for adding a list of videos, and for defining a background image, and that you can configure what kind and format of menu it is by passing arguments to the Menu() constructor function. Here's the new thumb_menu function using it: def thumb_menu(self, background): print "Creating a thumbnail menu with a background image." self.menu = Menu('DVD', 'thumbnail') self.menu.add_videos(self.videos) self.menu.set_background(background) The video titles added to the menu should be the same ones that were given to the add_videos function, which implies that the DVD class somehow stores that list. Above, I'm assuming it's in self.videos. It would be nice if add_videos actually added some videos to that list. I'm hoping to read some in from a directory, but am too lazy to look up how to do that right now, so I just write a little example; I can come back and do it the right way later: def add_videos(self, directory): print "Adding videos in %s" % directory for filename in "Second.mpg", "Third.mpg": title = filename.rstrip('.mpg') self.videos.append(Video(filename, title)) In the middle of writing this function, it occurs to me that there ought to be a Video class, to make it easy to pass around filenames and titles. So I treat self.videos as a list of Video objects, and append to it. Don't worry about leaving stuff half-implemented or missing; Python will warn you if you forget to implement Video: >>> mydvd = DVD() >>> mydvd.add_videos('/foo') DVD: Adding videos in /foo Traceback (most recent call last): File "", line 1, in ? File "libtovid/__init__.py", line 92, in add_videos self.videos.append(Video(filename, title)) NameError: global name 'Video' is not defined Not a problem; at this point, the Video class has just about written itself: class Video: def __init__(self, filename, title): print "Creating a Video from file %s entitled %s" %\ (filename, title) I can then build on this later if necessary. This is a quick and easy way to work out a desired program structure; think of it as a program outline, where all the details can be filled in later. -- Wapcaplet 07:16, 9 November 2006 (UTC)